{ "cells": [ { "attachments": {}, "cell_type": "markdown", "id": "3a271506", "metadata": {}, "source": [ "# 2-mode Grover's search algorithm" ] }, { "attachments": {}, "cell_type": "markdown", "id": "34fa32af", "metadata": {}, "source": [ "We implement in this notebook a 2-mode optical realization of Grover's search algorithm, based on Kwiat et al. (2000). Grover’s search algorithm: An optical approach. [Journal of Modern Optics](https://doi.org/10.1080/09500340008244040), 47(2–3), 257–266." ] }, { "attachments": {}, "cell_type": "markdown", "id": "e22c5dde", "metadata": {}, "source": [ "## Introduction" ] }, { "attachments": {}, "cell_type": "markdown", "id": "c04c528f", "metadata": {}, "source": [ "### Motivation\n", "\n", "Searching for a specific item (called the marked item) in an unstructured list of $N$ items requires $O(N)$ accesses to the list classically. Grover showed in 1996 that is possible for a quantum computer to achieve this using only $O\\left(\\sqrt{N}\\right)$ iterations." ] }, { "attachments": {}, "cell_type": "markdown", "id": "08145e4a", "metadata": {}, "source": [ "### Algorithm summary\n", "\n", "For a list of size $N$, Grover's algorithm requires $\\log (N)$ qubits. The algorithm starts by setting each qubit in the superposition state $\\frac{1}{\\sqrt{2}}\\left(|0\\rangle+|1\\rangle\\right)$. Then it applies $O\\left(\\sqrt{N}\\right)$ iterations of a subroutine called inversion-about-mean, whose goal is to skew this initial uniform superposition state towards the desired marked state such the probability of measuring the marked state is amplified. This subroutine requires the application of an oracle unitary, which applies a relative $\\pi$ phase shift only to the quantum state encoding the item we are looking for in the database." ] }, { "attachments": {}, "cell_type": "markdown", "id": "5690fa9d", "metadata": {}, "source": [ "### Kwiat et al. implementation details\n", "\n", "The optical implementation of Kwiat et al. uses the polarization and path degree of freedom of a single beam to achieve a 2-qubit optical implementation of Grover's search algorithm. Although $N=4$ here, calculations show that only a single application of the inversion-about-mean subroutine is required.\n", "\n", "In an effort to reduce the number of optical components used in the experimental setup, the authors work with a compiled version of the circuit, which we will reproduce here using Perceval." ] }, { "attachments": {}, "cell_type": "markdown", "id": "7bc2f8dc", "metadata": {}, "source": [ "## Perceval implementation" ] }, { "attachments": {}, "cell_type": "markdown", "id": "904f535e", "metadata": {}, "source": [ "### Initialisation" ] }, { "cell_type": "code", "execution_count": 1, "id": "4d4c8ff1", "metadata": {}, "outputs": [], "source": [ "from tabulate import tabulate\n", "import numpy as np\n", "import sympy as sp\n", "import matplotlib.pyplot as plt\n", "\n", "import perceval as pcvl" ] }, { "attachments": {}, "cell_type": "markdown", "id": "09fa856a", "metadata": {}, "source": [ "We create in Perceval a circuit with two spatial modes, $a$ and $b$ denoting resapectively the lower and upper spatial modes. For clarity, the different equivalent encodings for each of the four basis states are given below in order:\n", "- marked item encoding: $\\left|\"00\"\\right\\rangle$, $\\left|\"01\"\\right\\rangle$, $\\left|\"10\"\\right\\rangle$, $\\left|\"11\"\\right\\rangle$\n", "- Kwiat et al. path and polarization encoding: $\\left|aH\\right\\rangle$, $\\left|aV\\right\\rangle$, $\\left|bH\\right\\rangle$, $\\left|bV\\right\\rangle$\n", "- Perceval path and polarization encoding: $\\left|0, 1:H\\right\\rangle$, $\\left|0, 1:V\\right\\rangle$, $\\left|1:H, 0\\right\\rangle$, $\\left|1:V, 0\\right\\rangle$\n", "\n", "We first define these states and their mode equivalent in Perceval:" ] }, { "cell_type": "code", "execution_count": 2, "id": "b8084f08", "metadata": {}, "outputs": [], "source": [ "states = [pcvl.BasicState(\"|0,{P:H}>\"),\n", " pcvl.BasicState(\"|0,{P:V}>\"),\n", " pcvl.BasicState(\"|{P:H},0>\"),\n", " pcvl.BasicState(\"|{P:V},0>\"),\n", " ]\n", "\n", "states_modes = [\n", " pcvl.BasicState([0, 0, 0, 1]),\n", " pcvl.BasicState([0, 0, 1, 0]),\n", " pcvl.BasicState([0, 1, 0, 0]),\n", " pcvl.BasicState([1, 0, 0, 0])\n", "]" ] }, { "attachments": {}, "cell_type": "markdown", "id": "fab191db", "metadata": {}, "source": [ "We use the following unitary matrix to represent the beamsplitters:" ] }, { "cell_type": "code", "execution_count": 3, "id": "a3560b8f", "metadata": {}, "outputs": [ { "data": { "text/html": [ "$\\left[\\begin{matrix}\\frac{\\sqrt{2}}{2} & - \\frac{\\sqrt{2}}{2}\\\\\\frac{\\sqrt{2}}{2} & \\frac{\\sqrt{2}}{2}\\end{matrix}\\right]$" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "BS = pcvl.BS.Ry()\n", "pcvl.pdisplay(BS.U)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "54638f8d", "metadata": {}, "source": [ "The half-wave plates are defined in the article as:" ] }, { "cell_type": "code", "execution_count": 4, "id": "54d17968", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ξ=pi/2\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "0\n", "0\n", "" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def HWP(xsi):\n", " hwp = pcvl.Circuit(m=1)\n", " hwp.add(0, pcvl.HWP(xsi)).add(0, pcvl.PS(-sp.pi/2))\n", " return hwp\n", "\n", "pcvl.pdisplay(HWP(sp.pi/2))" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3d3c98ab", "metadata": {}, "source": [ "### Circuit Construction" ] }, { "attachments": {}, "cell_type": "markdown", "id": "b2c267cb", "metadata": {}, "source": [ "We divide the compiled circuit of Kwiat et al. in three parts: [state initialization](#state-initialization-circuit), [oracle](#oracle) and [inversion about mean](#inversion-about-mean). However, due to the compilation, each individual part does not act exactly as described in the introduction." ] }, { "attachments": {}, "cell_type": "markdown", "id": "14ee9683", "metadata": {}, "source": [ "\n", "#### State initialization circuit" ] }, { "cell_type": "code", "execution_count": 5, "id": "f6718866", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ξ=pi/8\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ry\n", "\n", "\n", "Φ=-pi\n", "\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "init_circuit = (pcvl.Circuit(m=2, name=\"Initialization\")\n", " // HWP(sp.pi / 8)\n", " // BS\n", " // pcvl.PS(-sp.pi))\n", "\n", "pcvl.pdisplay(init_circuit)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "e8278f70", "metadata": {}, "source": [ "#### Oracle\n", "\n", "The oracle circuit can be initialised so that any one of the four list elements are marked. This is controlled via the integer parameter $mark \\in [0, 3]$." ] }, { "cell_type": "code", "execution_count": 6, "id": "96aba62a", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "ξ=0\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "\n", "δ=pi/2\n", "\n", "\n", "\n", "ξ=0\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def oracle(mark):\n", " \"\"\"Values 0, 1, 2 and 3 for parameter 'mark' respectively mark the elements \"00\", \"01\", \"10\" and \"11\" of the list.\"\"\"\n", " oracle_circuit = pcvl.Circuit(m=2, name='Oracle')\n", " # The following dictionnary translates n into the corresponding component settings\n", " oracle_dict = {0: (1, 0), 1: (0, 1), 2: (1, 1), 3: (0, 0)}\n", " PC_state, LC_state = oracle_dict[mark]\n", " # Mode b\n", " if PC_state == 1:\n", " oracle_circuit //= HWP(0)\n", " oracle_circuit.add(0, pcvl.PR(sp.pi/2))\n", " if LC_state == 1:\n", " oracle_circuit //= HWP(0)\n", " # Mode a\n", " if LC_state == 1:\n", " oracle_circuit //= (1, HWP(0))\n", " if PC_state == 1:\n", " oracle_circuit //= (1, HWP(0))\n", " return oracle_circuit\n", "\n", "pcvl.pdisplay(oracle(0))" ] }, { "attachments": {}, "cell_type": "markdown", "id": "50596a16", "metadata": {}, "source": [ "#### Inversion about mean" ] }, { "cell_type": "code", "execution_count": 7, "id": "ef839994", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ry\n", "\n", "\n", "\n", "ξ=pi/4\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ry\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "inversion_circuit = (pcvl.Circuit(m=2, name='Inversion')\n", " // BS\n", " // HWP(sp.pi / 4)\n", " // BS)\n", "\n", "pcvl.pdisplay(inversion_circuit)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "4daf70f2", "metadata": {}, "source": [ "#### Detection\n", "\n", "The article also uses a detection circuit of the form:" ] }, { "cell_type": "code", "execution_count": 8, "id": "31ad50c7", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "0\n", "1\n", "2\n", "3\n", "0\n", "1\n", "2\n", "3\n", "" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "detection_circuit = pcvl.Circuit(m=4, name='Detection')\n", "detection_circuit.add((0, 1), pcvl.PBS())\n", "detection_circuit.add((2, 3), pcvl.PBS())\n", "\n", "pcvl.pdisplay(detection_circuit)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "76acc62f", "metadata": {}, "source": [ "However, Perceval allows us to filter out the photon's polarization state, meaning that there is no need to expand the circuit to four output spatial modes.\n", "\n", "For now, we will need this particular circuit." ] }, { "attachments": {}, "cell_type": "markdown", "id": "2326568e", "metadata": {}, "source": [ "#### Final circuit setup \n", "\n", "As above, the value of parameter 'mark' indicates which element of the list needs to be found." ] }, { "cell_type": "code", "execution_count": 9, "id": "1b0bffde", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Grover optical circuit for searching database element \"00\":\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "INITIALIZATION\n", "\n", "\n", "\n", "ξ=pi/8\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ry\n", "\n", "\n", "Φ=-pi\n", "\n", "\n", "ORACLE\n", "\n", "\n", "\n", "ξ=0\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "\n", "δ=pi/2\n", "\n", "\n", "\n", "ξ=0\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "INVERSION\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ry\n", "\n", "\n", "\n", "ξ=pi/4\n", "δ=pi/2\n", "\n", "\n", "Φ=-pi/2\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Ry\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "DETECTION\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "0\n", "1\n", "2\n", "3\n", "0\n", "1\n", "2\n", "3\n", "" ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def grover_circuit(mark):\n", " grover_circuit = pcvl.Circuit(m=4, name='Grover')\n", " grover_circuit.add(0, init_circuit).add(0, oracle(mark)).add(0, inversion_circuit)\n", " grover_circuit.add(1, pcvl.PERM([1, 0])).add(0, detection_circuit)\n", " return grover_circuit\n", "\n", "print('Grover optical circuit for searching database element \"00\":')\n", "pcvl.pdisplay(grover_circuit(0), recursive=True)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "922a8f12", "metadata": {}, "source": [ "## Grover algorithm execution\n", "\n", "We can finally simulate Grover's algorithm for marked database elements \"00\", \"01\", \"10\" and \"11\"." ] }, { "cell_type": "code", "execution_count": 10, "id": "0f000dac", "metadata": {}, "outputs": [ { "data": { "image/png": "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NWsWn376KZ999hlffPFFpbskNVmbNm3o1KkT6667Lq1bt650dyRVsbJtephSOqlcdUnSymjRokW8++67zJw5s9JdkVpkwYIFfPTRR8yZM4euXbsakEhqtrLvwB4R6wLHATsB6wEPpZR+k+f1BLoDD6aUPit325K0Ips5c+biQKRz58506tSJtm3b+siLqsqiRYuYM2cO7733HvPmzeOjjz5igw02qHS3JFWpsgYjETEY+D+gI9k8kgS8VavIxsBdwInATeVsW5JWdDNmZKuab7DBBqy77roV7o3UPK1atWKttdYC4O2332bWrFkGI5KarWz7jETELsAtwELgx2QjI3X/3PcQMBP4ZrnalaRqMX/+fADWXHPNCvdEarkOHToA2SNbLsIgqbnKOTLyc7Kd1fdJKY0Hlnr0IKX0RUSMB3qVsV1Jqio+X6+VQatWX/4902BEUnOVcwf2XYFxhUCkAe8CXcrYriRJkqQqVM5gpD3wQQnl1iljm5IkSZKqVDmDkbeAng0ViOy5rV7AG2VsV5IkSVIVKmcwMgroERFHN1DmFOCrwH1lbFeSJElSFSpnMHIJ2UpZN0TEryOib57eISK2j4gLgD+QPcr1uzK2K0mqcsOGDSMiGDZs2FJ5c+fO5dxzz+VrX/saa6yxBl/5ylf49re/zVtvvbV0RU00btw49t9/fzbccENWX311hg4dulSZbt26ERFLHGuuuSY77rgjl156KQsWLCi5vcL7rKmpabBc//79iQjGjBmzRPqUKVNo1aoVnTp1onfv3lx66aUlty1JK6Jy7sA+PSIOBO4AzgR+QrbPyBH5EcD7wCEppffL1a4krWy6nb3iDx5PueTA5dLOvHnz2HPPPXnyySfp0qULhxxyCFOmTOG6667jb3/7G08++SSbb755s+qePXs2+++/PzNnzqRXr14MGDCA3r17Fy1/+OGH07FjR1JKTJkyhXHjxvHMM89w77338sADD9CmTZtmvsvSdezYkeOOO4733nuP0aNHc+aZZ7LRRhtx3HHHLfO2JWlZKOumhymlcRHRAzgZ2AfoRjb6Mh14ALgmpTSznG1KklZeF110EU8++SS77LIL//znP+nYsSMAl19+OT/+8Y/59re/vdToQanGjRvHzJkz2WOPPUqq49JLL6Vbt26LXz/33HP079+fRx55hD//+c+cfvrpzepHU6y33nrccMMNANx8880cd9xxjBo1ymBEUtUq52NaAKSUZqWUrkgpHZhS6plS2jqltE9K6TcGIpKkUi1YsIA//vGPAPzpT39aHIgAnHHGGWy77baMHTuWZ599tln1v/feewDstNNOzbq+d+/enHHGGQCMHDmyWXW0xI477gh8+T6Keeedd3jllVeWR5ckqcnKHoxIklQOjz/+ODNnzqR79+5sv/32S+UfccQRANx7773Nqn/hwoUAtG/fvtl9LPTrzTffbHYdzVV4LOzzzz9vsNyrr77K1ltvTd++fbn66quZMWPG8uieJJWkbMFIROwaEf8TETdFxH0R8beIuCEizo6IncvVjiRp1fD8888D0KdPn3rzC+kTJkxYbn2qa9asWQC0bdt2ifTCpPfmPkJWTt26dWPvvffmX//6F6eddhpdunRh8ODB3HfffYsDMkmqlBbPGYmIbYFrgcKfraJOkZSXexo4OaX0UkvblCSt/KZNmwbAJptsUm9+IX3q1KnNqn/+/PkAtG7dulnXw5ejMttuu22z62iuQr8bW82rW7duPPDAA7z11lvcfPPN3HjjjYwYMYIRI0aw4YYbcuyxx3LiiSdW5D1IUotGRiJiR+BxoA/wGdlKWucA3wdOBX4B3JXn7QyMi4ilx9olSapj9uzZQPHHqDp06AB8OTrRVJMnTwaySeFNkVJi6tSpnH322dx6661EBN/73veWKNO9e3d69OhRtO/XX3/9UssF1z7Gjh3baD86d+4MwBtvvMGiRYsaLb/xxhtz1llnMXHiRJ599lmGDBkCZIsBbLfddvTp04crr7ySDz74oNG6JKlcmj0yEhGtgZuBDsBfgB+nlD4tUnZN4HLg28AtEbFNSik1t21Jkppr1qxZPP744/zlL3+hVatWDBgwoKTrNttss6XS2rRpwxVXXEG/fv2WSH/ooYcarKt79+7svvvuRfNHjRrV6MT0Dh06sNNOO/H000/z85//nB/96EdstNFGRNR9QGFpffr0oU+fPvz2t7/lH//4BzfeeCN33303Q4YM4cwzz+Tkk0/m6quvbrQeSWqpljymdQiwBfDXlNJ3GiqYBymnREQnsj1HBgH3tKBtSdJKrrB61meffVZv/pw5cwDo1KlTyXUOGTKEK6+8Esge8/q///s/ttpqq5KuLewzEhF07NiRrbbaisMOO4yvfOUrJbdfsPvuu9e7wWNB//79Gw1GAG677TZOO+00fv3rX/PrX/+atdZai08++aTkfqy22moceOCB7LTTTvTq1YsLLriAzz//nHHjxpVchyS1REuCkUHAIuDnTbjmZ2TByKEYjEiSGtC1a1cApk+fXm9+IX3TTTctuc6ddtqJww47jKeffprp06dz++23c8ghh9CqVeNPLdfdZ2RF8Mwzz/DII4/Qpk0b9thjD7p3717ytXPnzuWee+7hpptuYtSoUSxcuJB27doxePBgvvOdBv/GKEll05JgZAfg1ZTSG6VekFJ6PSJeya+VJKmo7bbbDoDx48fXm19Ib8rE62OOOYZjjjmGuXPn0rdvX4YPH87JJ5/MXnvt1fIOV8CQIUOYPXs248aNo2/fvo2WTykxduzYxZPYP/00e7p69913p6amhsGDB7Pmmmsu625L0mItCUa6AI8147rXgOIPykqSBOy2226stdZaTJ48meeee47evXsvkT9ixAgABg0a1OS627Vrx1FHHcWECROYOHFiVQYjM2bMYPr06Xzta19rNBB5+eWXufHGG7n55psXr1LWrVs3hgwZwgknnNCkERVJKqeWrKa1FtCcHdU/BfyziySpQW3atOH0008H4Ac/+MHiOSKQrQA1YcIE9thjD3bYYcnB9jFjxhARjT5SteGGGwIwc2Zz/itr2F577cVWW23F008/Xfa6CwqjGoX3Uczjjz/ONttsw8UXX8zHH39MTU0No0eP5vXXX+f88883EJFUUS0ZGVmNbM5IUy1qYbuSpFXEOeecw4MPPsgTTzzBlltuSb9+/Zg6dSpPPfUU66+/Ptdee+1S1xSWuV199dUbrLuwT8eyWNxx8uTJTJ06tejk+3Io9Lux+S6LFi1ir7324sQTT+Twww9v0Y7zklRuBgWStIKZcsmBle7CCmONNdZg9OjRXHzxxdxyyy2MHDmSzp07U1NTw4UXXljvhoiFndtPOOGE5d3dFVK/fv148MEHK90NSapXS4OREyPixLL0RJKkerRr144LLriACy64oKTyo0ePpnPnzos39SumTZs2wJc7sRczZcqUktot5ZqamhpqamoavX7MmDGNlin0u23btk3omSStWFoajDS+s1L93PBQklR2X3zxBY888gg//elPG91/pEuXLgDLdF7HsvSvf/0L+PJ9SFI1anYwklJqyeR3SZLKrnXr1iVv+te3b1/WXXddHn74YXr16kWvXr04+uijOfTQQ5dpH1viww8/5IwzzuC9995j9OjRABx00EEV7pUkNZ8BhSRpldSuXTvuv/9+DjjgAN5//31GjBjBc889V+luNWj27NncdNNNPP744/Ts2ZPf/e53HHHEEZXuliQ1mxPYJUmrrB133JH77ruv0t0oWbdu3RavFiZJKwNHRiRJFde7d2/OO++8pTY2lCSt3BwZkSRVXO/evQ1EJGkV5MiIJEmSpIowGJEkSZJUEQYjkiRJkirCYESSJElSRRiMSJIkSaoIgxFJkiRJFWEwIkmSJKkiDEYkSZIkVYTBiCRJkqSKcAd2SVrRDF2r0j1o3NCZZa1u2LBhnHTSSVx33XXU1NQskTd37lwuvvhibr31VqZNm0bnzp3Zb7/9uPDCC9l4441b1O64ceO44IILGD9+PB9//DH/8z//w9ChQ5co061bN6ZOnbpEWqdOnejRowdHHXUUP/zhD2nTpk2D7Xz66adsuOGGzJ8/nylTptC1a9cGy5922mlcffXVnHHGGVx22WUADB06lF/+8pess8469OnTh/POO49ddtml6W9aklYgjoxIklZY8+bNY8899+TCCy9k9uzZHHLIIXz1q1/luuuuY/vtt+f1119vdt2zZ89m//33Z9SoUWywwQYcfvjh9O7du2j5ww8/nBNPPJETTjiB7bffnueff54zzzyTffbZhwULFjTY1pprrsnBBx9MSombb765wbKff/45t912GwDHH3/84vTevXtzxBFHsNFGG/GPf/yDAw44gNmzZ5f+hiVpBWQwIklaYV100UU8+eST7LLLLrz22mv89a9/5amnnuKyyy7jgw8+4Nvf/naz6x43bhwzZ85kjz32YOLEidx6660ceuihRctfeumlDBs2jOuvv56xY8fy9NNPs9Zaa/HII4/w5z//udH2CoFFY8HI/fffz0cffUSvXr2WCI4OPfRQhg8fzoQJE9hnn3345JNPePLJJ0t6r5K0ojIYkSStkBYsWMAf//hHAP70pz/RsWPHxXlnnHEG2267LWPHjuXZZ59tVv3vvfceADvttFOzru/duzdnnHEGACNHjmy0/H777cf666/Piy++yL///e+i5W666SYAjjvuuKJlvvGNbwBfvodinn32WT799NNG+yZJlWIwIklaIT3++OPMnDmT7t27s/322y+Vf8QRRwBw7733Nqv+hQsXAtC+fftm97HQrzfffLPRsqutthpHHXUUUHx05NNPP+Xee++lVatWHHvssUXrKsxR+fzzzxts8w9/+AMbbbQRxx57LA888ACLFi1qtJ+StDwZjEiSVkjPP/88AH369Kk3v5A+YcKE5danumbNmgVA27Ztl0jv1q0bEcGYMWOWSC88qjV8+PB6A4M77riDefPm0b9/fzbZZJMW92/gwIF85Stf4ZZbbmHgwIF07dqVn/3sZ7zyyistrluSysFgRJK0Qpo2bRpA0Q/lhfS6K12Vav78+QC0bt26WdfDl6My2267bUnld9ppJ772ta/x9ttv8/DDDy+VX3hEq/bE9foU+tzYxPljjjmGSZMm8eijj/Ld736XOXPmcMkll7D11lvTt29frr76ambMmFFS3yVpWTAYkSStkAorRRV7jKpDhw7Al6MTTTV58mQA1ltvvSZdl1Ji6tSpnH322dx6661EBN/73veWKNO9e3d69OhRb98LgUYh8Ch46623GDNmDO3atePwww9vsA+dO3de4j00Zvfdd+eaa67h3Xff5bbbbmPQoEGMHz+e0047jS5dujB48GDuu+++xY+uSdLyYjAiSVqlzJo1i1GjRvGXv/yFVq1aMWDAgJKu22yzzYgIWrVqRbdu3fj1r39NmzZt+NOf/kS/fv2WKPvQQw/xyiuv1Ds5/thjjyUiuPPOO5k7d+7i9MKjW4cccgidOnVqsC/9+/cnIvjLX/7CqFGjSl7it23btgwePJh77rmHt956iyuvvJJevXoxYsQIDjroIDbZZBPuv//+kuqSpHIwGJEkrZAKq2d99tln9ebPmTMHoNEP7rUNGTKENddck/3335/27dszYsQIttpqq5KuLewzUlNTw+mnn84f//hH3njjDU499dSS24csqNltt92YNWsW99xzz+L0Uh/RAujZsycjRoygffv27L///nTq1IkhQ4Y0qR/rr78+P/zhD7nmmmvYd999gWx1rldffbVJ9UhSS1T1DuwR0Q74GXA00BX4GBgF/CKl9FaJdawNHAAMAvoCGwPzgZeAW4CrUkoNL1ciSSq7wi7l06dPrze/kL7pppuWXOdOO+3EYYcdxtNPP8306dO5/fbbOeSQQ2jVqvG/zV166aV069at5LYacvzxx/PYY49x0003cdRRR/Hiiy/y/PPPs8EGGzBw4MBGr1+0aBF33HEHb775Jptssgk77rhjk5YonjZtGjfffDM33ngjL7/8MpBNuj/hhBM48sgjm/2+JKmpqjYYiYg1gIfJAoh3gLuBbsBJwEER0TelVMrWvD8B/gdIwHPAU8D6wG7ATsAREbFvSqn+P81JkpaJ7bbbDoDx48fXm19IL3XyOGQTuo855hjmzp1L3759GT58OCeffDJ77bVXyzvcBEceeSQ//OEP+cc//sGHH37IjTfeCMDRRx/Naqs1/l/zww8/zC233ML222/PE088wRprrNHoNTNnzmTEiBHcdNNNjB07lpQSHTt2pKamhhNPPJE99tiDiGjxe5Okpqjmx7TOIQtExgFfSykdlVLaGfgxWTBxbYn1zAF+A3RLKfVJKR2dUtoL+DowDdg9b0uStBztttturLXWWkyePJnnnntuqfwRI0YAMGjQoCbX3a5du8V7fkycOLFF/WyOtddemwMPPJDPP/+cW2+9leHDhwOlPaIFX/Z58ODBDQYiCxcu5G9/+xtHHXUUG220Eaeccgpjx45lwIABXH/99bz77rtcd911i+egSNLyVpXBSES0AU7PX/4gpbR45l5K6XJgArBHROzQWF0ppYtTSj9NKU2rk/4f4Oz85bfK03NJUqnatGnD6adnv+p/8IMfLJ4jAnD55ZczYcIE9thjD3bYYclf9WPGjCEiGn2kasMNNwSyEYNy22uvvdhqq614+umni5YpBB7nn38+06ZNY6uttlq8s3pjCruqF95DMaeeeiqDBg3itttuo2vXrlx00UVMmTKFhx56iBNOOGHximSSVCnV+pjWbsBawOSU0r/ryR8BbEs2D+TZFrTzfH7+SgvqkCQ10znnnMODDz7IE088wZZbbkm/fv2YOnUqTz31FOuvvz7XXrv0IHhhM8HVV1+9wboLe3WklMre78mTJzN16tSik+8BDjjgADp37syHH34IlD4qAl/2ubG5Lh07duS73/0uNTU17LLLLiXXL0nLS7UGI9vl5/ofJP4yvfQHieu3eX5+t4X1SFLphpb/L/XVao011mD06NFcfPHF3HLLLYwcOZLOnTtTU1PDhRdeWO+GiIWd20844YTl3d0madOmDUcddRRXX301EcGxxx5b9jZ+97vflb1OSSqnag1Guubn+pdY+TK99CVW6vej/Hx3qRdExItFsrq3sC+StEpq164dF1xwARdccEFJ5UePHk3nzp0bXeq2TZs2wJc7sRczZcqUktptzjVXXXUVV111VZPrL/S5bdu2Tb5WklYkVTlnBOiYn4uNfxceLC598fk6IuL7wN7AJ8Alza1HkrT8fPHFFzzyyCP85Cc/aXT/kS5dugA0OK9jRfXMM88AX74HSapW1ToyskxFRD/gSrLlfr+dUnq71GtTSj2L1PkisE15eihJqk/r1q355JNPSirbt29f1l13XR5++GF69epFr169OProozn00EOXaR+ba+TIkfz1r3/lxRdfZOLEiay33nrsvPPOle6WJLVItY6MFFbPal8kv7A8yKymVhwRvcgey2oD/CildFfTuydJWtG1a9eO+++/nwMOOID333+fESNG1LuE8Iriueee4/bbb+fdd99l//335+9//zvt2rWrdLckqUWqdWSksAzv0jMXl0yf2pRKI2Iz4J/AOsDQlNIfmtc9SVI12HHHHbnvvvsq3Y2SDB06lKFDh1a6G5JUVtU6MlJYcrdPkfxC+oRSK4yILsADQBfgypTS+c3vniSpKXr37s15551H7969K90VSdJyVK0jI48DM4HuEdE7pfRcnfwj8vO9pVQWEesA/yBb8eo64L/L1E9JUgl69+5tICJJq6CqHBlJKS0A/pi//FNELN5CNiLOINtfZGxK6dla6adHxCsRcXHtuiKiPXAf8HXgNuA7aVnsgCVJkiRpCdU6MgJwEdnSu7sC/4mIR8n2FdkZ+AD4dp3y6wE9yB7Dqu2XwC7AF8BC4C8RsVRjKaWaMvZdkiRJWuVVbTCSUpoXEQOAnwHHAIcCHwPDgF+klIptiFjXOvm5dV5PMTXN6qgkSZKkelXlY1oFKaW5KaVzU0pbpJTappS6pJROqi8QSSkNTSlF3RGOlFJNnt7gsdzelCRJkrSKqOpgRJIkSVL1MhiRJEmSVBEGI5IkSZIqwmBEkiRJUkUYjEiSJEmqiKpd2leSVlZfv/7rle5CoyaeOLGs9Q0bNoyTTjqJ6667jpqamqLlXn75Zc455xyefPJJPvjgA4455hiGDRu2RJn+/fszduzYJdI6dOjA5ptvziGHHMKZZ57JmmuuWVK/xowZw4ABA9hjjz0YM2ZM0XI1NTVcf/319fY/Imjfvj2bbrophx12GOeddx5t2rQpqf1ihg0bxlVXXcVLL71EmzZt6Nu3L+eccw677rpri+qVpOXNYESSVBVSShx88MFMmjSJ7t27c+ihh7L77rsXLb/vvvuy0UYbAfDWW2/xxBNPcNFFFzFixAieeOIJ1llnnaLXltOJJ57Ihx9+yOjRo/nVr35Fu3btOOecc5pd35AhQ7jyyitp164dAwcOZN68eTzwwAP885//ZMSIERx66KHl67wkLWMGI5KkqjBp0iQmTZrE5ptvzquvvkrr1q0bLH/22WfTv3//xa/feOMN9txzT1555RV++ctfcumlly7jHmcKIzePP/44u+++O6NGjWp2MPLggw9y5ZVXsu666zJu3Di23HJLAMaNG0f//v056aST6N+/P2uvvXaZei9Jy5ZzRiRJVeG9994DYIcddmg0EKnPZpttxvnnnw/AyJEjy9m1kuy4447Al++jOS6//HIAzjnnnMWBCMAuu+zC97//fT755BP+8pe/LHHNO++8wyuvvNLsNiVpWTIYkSRVhYULFwLQvn37Ztex/fbbA/Dmm2+WpU9NUZgn8vnnnzfr+rlz5/Lwww8DcMQRRyyVX0i79957l0h/9dVX2Xrrrenbty9XX301M2bMaFb7krQsGIxIklYZs2bNAqBt27ZLpPfv35+IWGoy/Irk1VdfZf78+ay//vpssskmS+X36dMHgAkTJiyR3q1bN/bee2/+9a9/cdppp9GlSxcGDx7MfffdtzjAk6RKMRiRJFWF+fPnAzTrEa2CwqjBtttuW5Y+NVWrVq1YsGBBs66dNm0aQL2BCGQrhq299trMmDFjcdAFWTDywAMPMG3aNH7961+z5ZZbMmLECA466CA22WQTfvzjHy8VwEjS8mIwIkmqCpMnTwZgvfXWa/K1b7/9NpdddtniORennnrqEvldu3alR48erLXWWvVeP3bsWCKi6HH99deX1I/OnTvz/vvvM3v27Ca/h8I1DT2m1qFDB4AlgpGCjTfemLPOOouJEyfy7LPPMmTIECCbh7LddtvRp08frrzySj744IMm902SmsvVtCRJK7S5c+cyfvx4LrvsMgD22muvkq4bMGDAUmkRwc9//nOOPfbYJdJvuOGGBuvacMMN2W+//YrmP/bYY4uDpYbsueee3HbbbZx++ulccMEFbLLJJrRqtfz/LtinTx/69OnDb3/7W/7xj39w4403cvfddzNkyBDOPPNMTj75ZK6++url3i9Jqx6DEUnSCuuKK67gv//7vwFYZ511+POf/8zAgQNLurawz0hE0K5dO7bYYgsOPvhgtthiiyb3Y6uttmpwPklNTU1Jwcj//u//0rZtW66//vrFoykzZswoaSnejh07AvDZZ58VLTNnzhwAOnXq1Gh9AKutthoHHnggO+20E7169eKCCy7g888/Z9y4cSVdL0ktZTAiSVphbbPNNgwePJjx48czefJkhg8fzrHHHlvSilp19xlZEbz00kv8/e9/p1WrVvTr14+uXbuWvBt7165dAZg+fXq9+XPmzOGTTz5hnXXWKSkYmTt3Lvfccw833XQTo0aNYuHChbRr147Bgwfzne98p/Q3JUktYDAiSVphDRw4kIEDB7Jw4UIOPvhg7r//foYPH87JJ59c6a41y09/+lM++ugjbr31Vo466qgmXdujRw/atm3LBx98wFtvvcXGG2+8RP748eOBhifnp5QYO3YsN954IyNGjODTTz8FYPfdd6empobBgwez5pprNvFdSVLzOYFdkrTCW2211TjuuOMAmDhxYoV703wTJ06kbdu2HHnkkU2+tl27duy5554A3H777UvljxgxAoBBgwYtlffyyy/z85//nG7dujFgwACuvfZaOnfuzLnnnsukSZN49NFHOfnkkw1EJC13BiOSpKqw4YYbAjBz5syy133CCSew1VZbcdddd5W97to+/fRTNthgAyKiwXLdunUjIhgzZswS6WeccQYAF110Ef/5z38Wp48bN45rrrmGtddee6lRo8cff5xtttmGiy++mI8//piamhpGjx7N66+/zvnnn0/37t3L8+YkqRl8TEuSVBUK+4uklMpe97Rp03j11VeXSaBTVymrZy1atAiA1VdffYn0vffemx/96EdceeWV9O7dm3322YcFCxbwwAMPkFLiuuuuW2oy/KJFi9hrr7048cQTOfzww1u0g70klZvBiCStYCaeWL2PIanlPvroI6ZPn87XvvY1+vbtu1T+FVdcQe/evfnjH//IAw88QJs2bdh77735xS9+wa677rpU+X79+vHggw8uj65LUpMZjEiSqkJh1anCTuzF1H20qRTFrunfv39JIzHDhg1rcOlf+LLfbdu2bbDc2LFjSSlx7rnnFt1tvqamhpqamkb7JUkrOueMSJKqQpcuXQB49tlnWbhwYYV703T/+te/gC/fRzGjR49m66235lvf+tby6JYkVZQjI5KkqrDZZpvRs2dPXnzxRXr06MEOO+zAwIEDOeWUUyrdtQbV1NTw0Ucf8fDDDwNw0EEHNVj+D3/4w/LoliStEBwZkSRVjbvuuosjjjiCefPmcdddd/HYY49VukuNuv7663nooYfYdNNNOffccxkyZEiluyRJKwxHRiRJVWPLLbesd4+NFdmyWP1LklYWjoxIkiqud+/enHfeefTu3bvSXZEkLUeOjEiSKq53794GIpK0CnJkRJIkSVJFGIxIkiRJqgiDEUmSJEkVYTAiSZIkqSIMRiRJkiRVhMGIJEmSpIowGJEkSZJUEQYjkiRJkirCYESSJElSRbgDuyStYF7eautKd6FRW7/yclnrGzZsGCeddBLXXXcdNTU1Rcu9/PLLnHPOOTz55JN88MEHHHPMMQwbNmyJMv3792fs2LFLpHXo0IHNN9+cQw45hDPPPJM111yzwf4sWrSITTfdlOnTp/PII4/Qr1+/Bsv/5je/4ac//Snf/OY3ueOOOxa/p1NOOYW11lqLXr16ceaZZ3LQQQc1WE9jZsyYwdChQxk5ciTvvvsuG220EYcddhhDhw5l7bXXblHdklQJjoxIkqpCSomDDz6YO++8k3bt2nHooYey++67Fy2/7777cuKJJ3LiiSeyyy67MHnyZC666CJ23nlnZsyY0WBbrVq14phjjgHgpptuarRvhTLHH3/84rQtttiCo446ii222IJHHnmEb37zm7zxxhulvNV6ffjhh+y00078/ve/Z7XVVuPQQw+lU6dOXHnlley88858/PHHza5bkirFYESSVBUmTZrEpEmT2HzzzXn11Ve57bbbOOWUU4qWP/vssxk2bBjDhg3jgQce4IUXXqBbt2688sor/PKXv2y0vUJgcfvtt7NgwYKi5SZMmMDEiRPp3LkzBxxwwOL03XffnZtvvpmnnnqKU045hc8//5yHHnqoCe94SUOGDGHSpEl885vf5NVXX+Wvf/0rL7zwAv/v//0/XnvtNc4444xm1y1JlWIwIkmqCu+99x4AO+ywA61bt27y9Zttthnnn38+ACNHjmy0fK9evejduzczZszgvvvuK1quMCpy5JFH0qZNm3rL7LjjjsCX76Gp3nnnHYYPH06bNm246qqrWG21L5+y/u1vf8v666/PTTfdxPvvv7/Edc8++yyffvpps9qUpOXBYESSVBUWLlwIQPv27Ztdx/bbbw/Am2++WVL54447DoCbb7653vyUEsOHDweWfESrrkKQ8vnnn5fc19pGjRrFokWL6NevHxtuuOESeW3btmXQoEF88cUX/P3vf18i7w9/+AMbbbQRxx57LA888ACLFi1qVvuStKwYjEiSVhmzZs0Csg/wtfXv35+IWGoy/DHHHEPr1q3529/+xsyZM5eqb8yYMUyfPp3u3buz6667LrN+P//88wD06dOn3vxC+oQJE5ZIHzhwIF/5yle45ZZbGDhwIF27duVnP/sZr7zyyjLrqyQ1hcGIJKkqzJ8/H6BZj2gV3HvvvQBsu+22JZXv0qULe+21F/Pnz+f2229fKr/wiFZhBKWYQp8bmnvSkGnTpgGwySab1JtfSJ86deoS6ccccwyTJk3i0Ucf5bvf/S5z5szhkksuYeutt6Zv375cffXVjU7ml6RlyWBEklQVJk+eDMB6663X5GvffvttLrvsMi6//HIATj311CXyu3btSo8ePVhrrbWWurbw+FXdVbXmzZu3eBnfxoKRzp07L/Eemmr27NlA8UfUOnToAHw58lPX7rvvzjXXXMO7777LbbfdxqBBgxg/fjynnXYaXbp0YfDgwdx3332LH4WTpOXFfUYkSSu0uXPnMn78eC677DIA9tprr5KuGzBgwFJpEcHPf/5zjj322CXSb7jhhqL1HHbYYXTo0IFHHnmEN998k69+9asAix/d6tu3L1tssUWDfdlll11YY401GDlyJH/961/Zd999K7IvSNu2bRk8eDCDBw/mgw8+YPjw4dxwww2MGDGCESNGsOGGG3Ldddex//77L/e+SVo1OTIiSVphXXHFFbRv357dd9+dGTNm8Oc//5mBAweWdG1hn5GamhpOPfVULrvsMl577bWSlvWtrUOHDhx22GGklLjlllsWp9e3t0gxnTt3ZtSoUWy55ZYcffTRrLPOOhx66KEl96Fjx44AfPbZZ/Xmz5kzB4BOnTqVXOf666/PD3/4Q6655hr23XdfIFvt69VXXy25DklqKUdGJEkrrG222YbBgwczfvx4Jk+ezPDhwzn22GNLWlHr7LPPpn///mXpx/HHH89NN93EzTffzE9/+lM+/vhj7r//flZffXWOOuqokuq47777ePnll1lvvfXYZZdd2HPPPUtuv2vXrgBMnz693vxC+qabblpSfdOmTePmm2/mxhtv5OWXXwagW7dunHDCCRx55JEl90uSWspgRJK0who4cCADBw5k4cKFHHzwwdx///0MHz6ck08+ebn2Y6+99qJLly5MnDiR559/nnHjxrFgwQIOPvhg1l133UavnzRpEr/97W/p0qULL730UpMf0dpuu+0AGD9+fL35hfSGJubPnDmTESNGcNNNNzF27FhSSnTs2JGamhpOPPFE9thjDyKiSf2SpJYyGJEkrfBWW201jjvuOO6//34mTpy43Ntv3bo13/rWt7j88su5+eabGTduHFDaI1rA4j4PGjSoWXNF9ttvP1q1asWjjz7K+++/zwYbbLA4b/78+dx77720bt16iR3gIdubZdSoUdx4443cc889zJs3j4hgwIABnHjiiRx++OGLJ79LUiU4Z0SSVBUKm/3Vt99HS51wwglstdVW3HXXXUXLFAKPa6+9lscff5y1116bQYMGlVR/YRf0uhsW1jVmzBgigm7dui2R3qVLF771rW+xYMECTjvttCVWvTrrrLP44IMPOO6445YIUiBbNWzQoEHcdtttdO3alYsuuogpU6bw0EMPccIJJxiISKo4R0YkSVWhsFdHSqnsdU+bNo1XX321wUCnd+/e9OrVixdeeAGAwYMHL7V5YjGFPrdq1fDfAAs7pK+++upL5V1xxRU8+eST3HHHHWy11VZ84xvf4MUXX+SFF15gyy23XLxscW0dO3bku9/9LjU1Neyyyy4l9VWSlieDEUlawWz9ysuV7oKKOP744/npT38KNL63SHMUdlo/4YQTlspbb731ePrppxk6dCgjR47krrvuYsMNN+SHP/wh559/fr2Pf/3ud78rex8lqZwMRiRJVaFNmzbAlzuxFzNmzJgm113qNWeddRZnnXVWk+sv9LmxkZTRo0fTuXNnhgwZUm9+586d+f3vf8/vf//7JvdBklZEzhmRJFWFLl26APDss89W3U7h//rXv4Av30N9vvjiCx555BF+8pOfNGm/EEmqZo6MSJKqwmabbUbPnj158cUX6dGjBzvssAMDBw7klFNOqXTX6vXYY49x9dVXM3nyZJ566inatm3LPvvsU7R869at+eSTT5ZfByVpBeDIiCSpatx1110cccQRzJs3j7vuuovHHnus0l0qatKkSdx666289tpr9O/fn7vvvpuNN9640t2SpBWKIyOSpKqx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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Circuit simulation\n", "input_state = pcvl.BasicState(\"|{P:H},0, 0, 0>\")\n", "results_list = [] # probability amplitudes storage\n", "\n", "for mark in range(4):\n", " sim = pcvl.Processor(\"SLOS\", grover_circuit(mark))\n", " ca = pcvl.algorithm.Analyzer(sim,\n", " input_states=[input_state],\n", " output_states=states_modes,\n", " )\n", " results_list.append(ca.distribution[0])\n", "\n", "# Plot data\n", "labels = ['\"00\"', '\"01\"', '\"10\"', '\"11\"']\n", "state_0_prob_list = results_list[0]\n", "state_1_prob_list = results_list[1]\n", "state_2_prob_list = results_list[2]\n", "state_3_prob_list = results_list[3]\n", "x = np.arange(4) # label locations\n", "width = 0.1 # the width of the bars\n", " \n", "fig, ax = plt.subplots(dpi=150)\n", "rects_0 = ax.bar(x - 3*width/2, state_0_prob_list, width, label=str(states[0]))\n", "rects_1 = ax.bar(x - width/2, state_1_prob_list, width, label=str(states[1]))\n", "rects_2 = ax.bar(x + width/2, state_2_prob_list, width, label=str(states[2]))\n", "rects_3 = ax.bar(x + 3*width/2, state_3_prob_list, width, label=str(states[3]))\n", "\n", "ax.set_xlabel('Marked database element')\n", "ax.set_ylabel('Detection probability') \n", "ax.set_xticks(x, labels)\n", "ax.legend()\n", "ax.grid(True, axis='x')\n", "plt.show()" ] }, { "attachments": {}, "cell_type": "markdown", "id": "659482dd", "metadata": {}, "source": [ "As demonstrated by the graph above, Grover's algorithm indeed finds the marked database element!" ] }, { "attachments": {}, "cell_type": "markdown", "id": "d32d028f", "metadata": {}, "source": [ "## Reference\n", "\n", "> Kwiat et al. Grover’s search algorithm: An optical approach. [Journal of Modern Optics](https://doi.org/10.1080/09500340008244040), 47(2–3), 257–266 (2000).\n" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }